#include <string>

#include "defines.h"
#include "manager.h"
#include "mapobj.h"
#include "tile.h"

using std::string;

MapObject::MapObject( int x, int y, string name, char symbol )
{
	map_ = nullptr;
	setPos( x, y );
	this->name = name;
	this->symbol = symbol;
	manager.getMObjs().push_back( this );
	isGhost = false;
	color = COLOR_WHITEB;
	layer = 1;
	objType type = { 0 };
	type_ = type;
	type.mapObject = 1;
	drawTo = false;
}

MapObject::~MapObject()
{
	setPos( -1, -1 );
	manager.getMObjs().remove( this );
}

inline int MapObject::getX() const
{
	return this->x;
}

inline int MapObject::getY() const
{
	return this->y;
}

bool MapObject::move( int direction )
{
	int xAdj = 0;
	int yAdj = 0;
	getAdj( direction, xAdj, yAdj );
	Tile * tileToStep = tileAt( getX() + xAdj, getY() + yAdj );
	if( tileToStep != nullptr && ( isGhost || tileToStep->passable ) )//check if the tile exists and we can step on it
	{
		setPos( getX() + xAdj, getY() + yAdj );
		return true;
	}
	else
		return false;
}

int MapObject::setPos( int x, int y )
{
	if( this->x == x && this->y == y )
		return 0;
	//remove ourselves from previous location's contents
	Tile * prevLoc = tileAt( this->x, this->y );
	if( prevLoc )
		prevLoc->removeFromContents( this );
	//add ourselves to the new location's contents
	Tile * newLoc =tileAt( x, y );
	if( newLoc )
		newLoc->addToContents( this );
	this->x = x;
	this->y = y;

	return 1;
}

inline int MapObject::setPos( const MapObject * mobj )
{
	return setPos( mobj->getX(), mobj->getY() );
}

int MapObject::setMapPos( map * m, int x, int y )
{
	if( map_ == m && this->x == x && this->y == y )
		return 0;
	Tile * prevLoc = mapTileAt( m, this->x, this->y );
	if( prevLoc )
		prevLoc->removeFromContents( this );
	Tile * newLoc = mapTileAt( m, x, y );
	if( newLoc )
		newLoc->addToContents( this );
	if( map_ != m )
	{
		if( map_ )
			map_->mapObjects.remove( this );
		m->mapObjects.push_back( this );
	}
	map_ = m;
	this->x = x;
	this->y = y;
	return 1;
}

void MapObject::draw()
{
	manager.mapaddch( y, x, symbol | color );
}

bool MapObject::isValidLoc() const
{
	if( x < 0 || y < 0 || x >= MAP_X || y >= MAP_Y )
		return false;
	return true;
}

objType MapObject::getType() const
{
	return type_;
}

void MapObject::hitEffect( int force )
{
}

void MapObject::showDesc() const
{
	WINDOW * w = newScreen();
	wattron( w, color );
	wprintw( w, "%s\n\n", name.c_str() );
	wattroff( w, color );
	if( description.empty() )
		wprintw( w, "%s", string( "This is " + name ).c_str() );
	else
		wprintw( w, "%s", description.c_str() );
	wrefresh( w );
	int action;
	while( ( action = getch() ) != ESC_KEY && action != ENTER_KEY )
		;
	deleteScreen( w );
}

//bool MapObject::visibleMessage( std::string msg )
//{
//
//}
//
//bool visibleMessage( const char * );

map * MapObject::getMap() const
{
	return map_;
}

MapObject::MapObject()
{
	map_ = nullptr;
	isGhost = false;
	drawTo = false;
	x = -1;
	y = -1;
	objType type = { 0 };
	type_ = type;
	type_.mapObject = 1;
	color = COLOR_WHITEB;
	layer = 1;
}

void MapObject::setMapObject( map * m, int x, int y, std::string name, char symbol )
{
	setMapPos( m, x, y );
	this->name = name;
	this->symbol = symbol;
}